#!/usr/bin/env luajit
-- -*- lua -*-
--
-- This tool converts the contents of a file to a C array of hex data,
-- that can be included as a C header. The data is \0 terminated.
--
-- Copyright (C) 2014-2020 Markus Klotzbuecher <mk@mkio.de>
--
-- SPDX-License-Identifier: BSD-3-Clause
--

local fmt = string.format

local function split(str, pat)
   local t = {}  -- NOTE: use {n = 0} in Lua-5.0
   local fpat = "(.-)" .. pat
   local last_end = 1
   local s, e, cap = str:find(fpat, 1)
   while s do
      if s ~= 1 or cap ~= "" then
	 table.insert(t,cap)
      end
      last_end = e+1
      s, e, cap = str:find(fpat, last_end)
   end
   if last_end <= #str then
      cap = str:sub(last_end)
      table.insert(t, cap)
   end
   return t
end

local function filename(path)
   local t = split(path, '/')
   return t[#t]
end

--- Convert arguments list into key-value pairs.
-- The return table is indexable by parameters (i.e. ["-p"]) and the
-- value is an array of zero to many option parameters.
-- @param standard Lua argument table
-- @return key-value table
function proc_args(args)
   local function is_opt(s) return string.sub(s, 1, 1) == '-' end
   local res = { [0]={} }
   local last_key = 0
   for i=1,#args do
      if is_opt(args[i]) then -- new key
         last_key = args[i]
         res[last_key] = {}
      else -- option parameter, append to existing tab
         local list = res[last_key]
         list[#list+1] = args[i]
      end
   end
   return res
end

function usage()
   print([[
ubx-tocarr: convert file contents to a C hex array

Usage: ubx-tocarr [OPTIONS]
   -s           source file
   -d           destination file
   -a           array name
   -h           show this.
]])
end

local opttab=proc_args(arg)

if #arg < 1 or opttab['-h'] then usage(); os.exit(1) end

if not (opttab['-s'] and opttab['-s'][1]) then
   usage()
   os.exit(1)
else
   srcfile=opttab['-s'][1]
end

if not (opttab['-d'] and opttab['-d'][1]) then
   usage()
   os.exit(1)
else
   outfile=opttab['-d'][1]
end

if not (opttab['-a'] and opttab['-a'][1]) then
   structname = string.gsub(filename(srcfile), "[-.]", "_")
else
   structname=opttab['-a'][1]
end


breaknum = 16	 -- break line after this

fi = assert(io.open(srcfile, "r"))
fo = assert(io.open(outfile, "w"))

data=fi:read("*a")

fo:write(fmt("static const char %s [] = {\n\t", structname))

for i=1,#data do
   fo:write(fmt("0x%.2x, ", string.byte(data, i)))
   if i % breaknum == 0 then fo:write("\n\t") end
end

fo:write("0x00 \n};\n")
